<?php namespace App\Http\Services;

use App\CommodityProperty;
use Auth;
use Illuminate\Support\Str;
use Request;
use Validator;
use DB;
use ZipArchive;

class Tools
{
    /**
     * 随机英文大小写数字字符串
     * @param $length
     * @return mixed
     */
    public static function randLetter($length)
    {

        $str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        return substr(str_shuffle($str),0,$length);
    }

    /** 前端麻烦路由 */
    public static function vue_route($request,$url,$get_array = null){
        $route = 'http://'.$request->getHttpHost().$request->getBaseUrl().$url;
        if ($get_array){
            foreach ($get_array as $key => $value){
                
                    $route = $route.'/'.$value;
            }
        }
        return $route;
    }

    /**
     * 生成优惠券吗
     * @param int $section
     * @param int $dlta
     * @return string
     */
    public static function create_guid($section = 4,$dlta = 4,$hyphen = "-") {
        $charid = strtoupper(md5(uniqid(mt_rand(), true)));
        $temp = 0;
        $uuid = '';
        for ($i = 0;$i < $section ;$i++){
            if ($i == $section-1)
                $uuid .= substr($charid, $temp, $dlta);
            else
                $uuid .= substr($charid, $temp, $dlta).$hyphen;
            $temp +=$dlta;
        }
        return $uuid;
    }
    /**
     * 时间戳变为便捷可视时间
     * @param $timestamp
     * @return string
     */
    public static function simpleTimestamp($timestamp)
    {
        $time = $timestamp;
        $now = time();

        $min = date('i',$time);
        $hour = date('Y-m-d H',$time);
        $day = date('Y-m-d',$time);
        $month = date('Y-m' ,$time);
        $year =date('Y',$time);

        $now_min = date('i',$now);
        $now_hour = date('Y-m-d H',$now);
        $now_day = date('Y-m-d',$now);
        $now_month = date('Y-m' ,$now);
        $now_year = date('Y',$now);

        $yesterday = date('Y-m-d',($now - 24*60*60));
       
        if ($now_hour == $hour && ($now_min - $min < 3))
        {
            if ($now_min - $min < 1)
            {
                $retime = "现在";
                return $retime;
            }
            else if(1<=$now_min - $min && $now_min - $min <2){
                $retime = '一分钟前';
                return $retime;
            }
            else {
                $retime = '两分钟前';
                return $retime;
            }
        }

        elseif ($now_day == $day)
        {
            // return $day;
            $sortime = date('H',$time);
            if ($sortime < 6)
            {
                $retime = date('凌晨   h:i',$time);
                return $retime;
            }
            else if ($sortime < 12)
            {
                $retime = date('早上   h:i',$time);
                return $retime;
            }
            else if($sortime < 18)
            {
                $retime = date('下午   h:i',$time);
                return $retime;
            }
            else if ($sortime < 24)
            {
                $retime = date('晚上   h:i',$time);
                return $retime;
            }
        }
        elseif ($day == $yesterday)
        {
            $retime = '昨天 ';

            $sortime = date('H',$time);
            if ($sortime < 6)
            {
                $retime .= date('凌晨  h:i',$time);
                return $retime;
            }
            else if ($sortime < 12)
            {
                $retime .= date('早上  h:i',$time);
                return $retime;
            }
            else if($sortime < 18)
            {
                $retime .= date('下午  h:i',$time);
                return $retime;
            }
            else if ($sortime < 24)
            {
                $retime .= date('晚上  h:i',$time);
                return $retime;
            }
        }

        elseif ($now_month == $month)
        {
            $retime = date('m 月 d 日 h:i',$time);
            return $retime;
        }
        elseif ($now_year > $year)
        {
            $retime = date('Y 年 m 月 d 日 h:i',$time);
            return $retime;
        }

    }

    /**
     * 全排不重复数组
     * @param $arrs
     * @param int $_current_index
     * @return array
     */
    public static function getArrSet($arrs,$_current_index=-1)
    {
        //总数组
        static $_total_arr;
        //总数组下标计数
        static $_total_arr_index;
        //输入的数组长度
        static $_total_count;
        //临时拼凑数组
        static $_temp_arr;

        //进入输入数组的第一层，清空静态数组，并初始化输入数组长度
        if($_current_index<0)
        {
            $_total_arr=array();
            $_total_arr_index=0;
            $_temp_arr=array();
            $_total_count=count($arrs)-1;
            self::getArrSet($arrs,0);
        }
        else
        {
            //循环第$_current_index层数组
            foreach($arrs[$_current_index] as $v)
            {
                //如果当前的循环的数组少于输入数组长度
                if($_current_index<$_total_count)
                {
                    //将当前数组循环出的值放入临时数组
                    $_temp_arr[$_current_index]=$v;
                    //继续循环下一个数组
                    self::getArrSet($arrs,$_current_index+1);

                }
                //如果当前的循环的数组等于输入数组长度(这个数组就是最后的数组)
                else if($_current_index==$_total_count)
                {
                    //将当前数组循环出的值放入临时数组
                    $_temp_arr[$_current_index]=$v;
                    //将临时数组加入总数组
                    $_total_arr[$_total_arr_index]=$_temp_arr;
                    //总数组下标计数+1
                    $_total_arr_index++;
                }

            }
        }

        return $_total_arr;
    }

    /**
     * 组合排序算法
     * @param array $arr
     * @param $move
     * @return array
     */
    public static function sortArr($arr = array(),$move){

       $result = array();

        if ($move ==1){

            return $arr;

        }

        if ($move == count($arr)){

            $result[] = implode(',' , $arr);

            return $result;

        }

        $temp_firstelement = $arr[0];

        unset($arr[0]);

        $arr = array_values($arr);

        $temp1 = self::sortArr($arr, ($move-1));

        foreach ($temp1 as $s){

            $s = $temp_firstelement.','.$s;

            $result[] = $s;

        }

        unset($temp2);

        $temp2 = self::sortArr($arr, $move);

        foreach ($temp2 as $s){

            $result[] = $s;

        }

        unset($temp2);

        return $result;
    }

    /**
     *  直接插入排序算法
     */
    public function ShellInsert(array &$a, $length ,$dkey){
        $keys = array_keys($a);
        for ($i = $dkey; $i < $length; $i++) {
            if ($a[$keys[$i]] < $a[$keys[$i - 1]]) {
                $temp = 0;
                $temp = $a[$keys[$i]];
                for ($j = $i - $dkey; $j >= 0 && ($temp < $a[$keys[$j]]); $j -= $dkey) {
                    $temp1[$keys[$j + $dkey]] = $a[$keys[$j + $dkey]];
                    $temp2[$keys[$j]] = $a[$keys[$j]];
                    $first_array = array_splice ($a,0,$j);
                    $a = array_merge ($first_array, $temp1, $a);
                    $first_array = array_splice ($a,0,$j + $dkey);
                    $a = array_merge ($first_array, $temp2, $a);
                }
            }
        }

    }
    /**
     *  增量选择公式
     *   希尔排序效率是变动的，而这变动取决于该排序“增量”的选择，目前该增量也是数学上的一大难题，但在还是有数学公式可以算出最优的增量
     *   dlta[k]=2^(t-k) + 1
     *   dlta[k]=1/2(3^(t-k)-1)    该公式用于n->正无穷
     *
     *  @param i      第i次增量
     *  @param length 排序趟数
     *
     *  @return 返回该值
     */
    public function dlta($i,$length){
        $i = intval($i);
        $key = pow(2, log(intval($length) -1,2) - $i) + 1;
        var_dump($key);
        return intval($key);
    }

    /**
     * 希尔插入排序
     * @param array $r 待排序数组
     * @param $length 数组长度
     */
    public static function ShellSort(array &$r, $length){
        $length = intval($length);
        $temp = new Tools();
        for ($k = 0; $k <= log($length -1,2) +1; $k++) {
            $dlta =  $temp->dlta($k, $length);
            $temp->ShellInsert($r, $length,$dlta);
        }
    }



    /**
     * 截取UTF8编码字符串从首字节开始指定宽度(非长度), 适用于字符串长度有限的如新闻标题的等宽度截取
     * 中英文混排情况较理想. 全中文与全英文截取后对比显示宽度差异最大,且截取宽度远大越明显.
     * @param string $str   UTF-8 encoding
     * @param int[option] $width 截取宽度
     * @param string[option] $end 被截取后追加的尾字符
     * @param float[option] $x3<p>
     *  3字节（中文）字符相当于希腊字母宽度的系数coefficient（小数）
     *  中文通常固定用宋体,根据ascii字符字体宽度设定,不同浏览器可能会有不同显示效果</p>
     *
     * @return string
     * @author waiting
     */
    public static function u8_title_substr($str, $width = 0, $end = '...', $x3 = 0) {
        global $CFG; // 全局变量保存 x3 的值
        if ($width <= 0 || $width >= strlen($str)) {
            return $str;
        }
        $arr = str_split($str);
        $len = count($arr);
        $w = 0;
        $width *= 10;

        // 不同字节编码字符宽度系数
        $x1 = 11;   // ASCII
        $x2 = 16;
        $x3 = $x3===0 ? ( $CFG['cf3']  > 0 ? $CFG['cf3']*10 : $x3 = 21 ) : $x3*10;
        $x4 = $x3;

        //UTF8
        for ($i = 0; $i < $len; $i++) {
            if ($w >= $width) {
                $e = $end;
                break;
            }
            $c = ord($arr[$i]);
            if ($c <= 127) {
                $w += $x1;
            }
            elseif ($c >= 192 && $c <= 223) {   // 2字节头
                $w += $x2;
                $i += 1;
            }
            elseif ($c >= 224 && $c <= 239) {   // 3字节头
                $w += $x3;
                $i += 2;
            }
            elseif ($c >= 240 && $c <= 247) {   // 4字节头
                $w += $x4;
                $i += 3;
            }
        }

        return implode('', array_slice($arr, 0, $i) ).$e;
    }

    /**
     * 截取需要使用的title
     * @param $title
     * @param int $sub_num
     * @return string
     */
    public static function getTitleForPay($title,$sub_num = 29){

        $count = 0;
        for($i = 0; $i < strlen($title); $i++)
        {
            $value = ord($title[$i]);
            if($value > 127) {
                $count++;
                if($value >= 192 && $value <= 223) $i++;
                elseif($value >= 224 && $value <= 239) $i = $i + 2;
                elseif($value >= 240 && $value <= 247) $i = $i + 3;
                else die('Not a UTF-8 compatible string');
            }
            $count++;
        }

        if ($count > 32)
        {

            $title = self::u8_title_substr($title, $sub_num);

        }

        return $title;

    }

    /**
     * 验证是否为合法的 Email 地址
     *
     * @param $str
     * @return bool
     */
    public static function isEmail($str)
    {
        return Validator::make(['email' => $str], ['email' => 'required|email'])->passes();
    }

    /**
     * 验证是否为合法的手机号码
     *
     * @param $str
     * @return bool
     */
    public static function isPhone($str)
    {
        return Validator::make(['phone' => $str], ['phone' => ['required', 'regex:/1\d{10}/']])->passes();
    }

    /**
     * 验证是否为合法的用户名
     *
     * @param $str
     * @return bool
     */
    public static function isUsername($str)
    {
        return Validator::make(['username' => $str], ['username' => 'required|alpha_dash'])->passes();
    }

    /**
     * 生成订单编号
     * @return string
     */
    public static function makeOrderNum(){
        $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
        $orderSn = $yCode[intval(date('Y')) - 2011] . strtoupper(dechex(date('m'))) . date('d') . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 999));
        return $orderSn;
    }

    /**
     * 生成订单编号
     * @return string
     */
    public static function makeBillNum(){
        $orderSn = date('Ymdhis',time()). substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 999));
        return $orderSn;
    }

    /**
     * 生成订单编号
     * @return string
     */
    public static function makeSellerBillNum(){
        $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
        $orderSn = $yCode[intval(date('Y')) - 2011] . date('Ymdhis',time()). substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 999));
        return $orderSn;
    }

    public static function makeDesignServiceNum(){
        $serviceSn = 'DS'.date('Ymdhis',time()). sprintf('%02d', rand(0, 999));
        return $serviceSn;
    }

    public static function makeRedPackageCode(){
        $code = 'RB#'.Str::quickRandom(6);
        return $code;
    }

    public static function buildApiResponse($message = '', $data = [], $redirect = '', $level = 'success', $code = 0, $httpStatusCode = 200)
    {
        if (Request::ajax() || Request::wantsJson()) {
            return response()->json([
                'code'     => $code,
                'level'    => $level,
                'message'  => $message,
                'data'     => $data,
                'redirect' => $redirect,
            ], $httpStatusCode);
        } else {
            return view('api/redirect', [
                'code'     => $code,
                'level'    => $level,
                'message'  => $message,
                'data'     => $data,
                'redirect' => $redirect,
            ]);
        }
    }

    /**
     * 开启sql 查询日志
     */
    public static function startSqlLog(){
        DB::connection()->enableQueryLog();
    }

    /**
     * 获取最后一条sql 查询日志
     * @return mixed
     */
    public static function getEndSqlLog(){
        $sql=DB::getQueryLog();
        return end($sql);
    }

    /**
     * 生成sql语句字符串
     * @param $table
     * @param array $colum
     * @param array|null $select
     * @return mixed
     */
    public static function getDatabaseSql($table,array $colum, $select = null){
        $sql =  DB::table($table);
        $sql = $sql->where('deleted_at','=',null);

        foreach ($colum as $key => $value){
            if (!is_int($key))
                $sql = $sql->where($key,'=',$value);
            else
                $sql = $sql->whereRaw($value);
        }
        if (is_array($select)){
            $sql = $sql->select($select);
        }else{
            $sql = $sql->selectRaw($select);
        }
        $sql = $sql->toSql();
        $value = array_values($colum);
        foreach ($value as &$temp){
            if (!is_int($temp) && !is_integer($temp)){
                $temp = '"'.$temp.'"';
            }
        }
        $sql = str_replace('?', '%s',$sql);
        $sql = vsprintf($sql, $value);

        return $sql;
    }

    /**
     * 获取二维数组的指定列
     * @param $input          多维数组
     * @param $columnKey      获取的列名
     * @param null $indexKey  指定列名作为返回的索引名
     * @return array
     */
    public static function getArrayColumn($input, $columnKey, $indexKey=null){
            if(!function_exists('array_column')){
                $columnKeyIsNumber  = (is_numeric($columnKey))?true:false;
                $indexKeyIsNull            = (is_null($indexKey))?true :false;
                $indexKeyIsNumber     = (is_numeric($indexKey))?true:false;
                $result                         = array();
                foreach((array)$input as $key=>$row){
                    if($columnKeyIsNumber){
                        $tmp= array_slice($row, $columnKey, 1);
                        $tmp= (is_array($tmp) && !empty($tmp))?current($tmp):null;
                    }else{
                        $tmp= isset($row[$columnKey])?$row[$columnKey]:null;
                    }
                    if(!$indexKeyIsNull){
                        if($indexKeyIsNumber){
                            $key = array_slice($row, $indexKey, 1);
                            $key = (is_array($key) && !empty($key))?current($key):null;
                            $key = is_null($key)?0:$key;
                        }else{
                            $key = isset($row[$indexKey])?$row[$indexKey]:0;
                        }
                    }
                    $result[$key] = $tmp;
                }
                return $result;
            }else{
                return array_column($input, $columnKey, $indexKey);
            }
    }

    public static function setColorNum(CommodityProperty $property){
        /** @var CommodityProperty $myParentProperty */
        $myParentProperty = $property->getParentProperty;
    }

    /**
     * 复制文件到新的地方
     * @param $src
     * @param $dst
     */
    public static function recurse_copy($src,$dst) {  // 原目录，复制到的目录
        $dir = opendir($src);
        @mkdir($dst);
        while(false !== ( $file = readdir($dir)) ) {
            if (( $file != '.' ) && ( $file != '..' )) {
                if ( is_dir($src . '/' . $file) ) {
                    self::recurse_copy($src . '/' . $file,$dst . '/' . $file);
                }
                else {
                    copy($src . '/' . $file,$dst . '/' . $file);
                }
            }
        }
        closedir($dir);
    }

    /**
     * [addFileToZip 打包压缩文件]
     * @param [type] $path     [文件路径]
     * @param [type] $saveName [保存压缩包名]
     */
    public static function  addFileToZip($path,$saveName,$needDownload = false)
    {
        $savePath = './';
        $zip = new \ZipArchive;
        if(file_exists($savePath.$saveName.'.zip')){

            unlink($savePath.$saveName.'.zip');

        }
        if (!file_exists($savePath.$saveName.'.zip'))
        {
            $zip->open($savePath.$saveName.'.zip',ZipArchive::CREATE);//创建一个空的zip文件
            $handler=opendir($savePath.$path); //打开当前文件夹由$path指定。
            while(($filename=readdir($handler))!==false){

                if($filename != "." && $filename != ".."){//文件夹文件名字为'.'和‘..’，不要对他们进行操作
                    if(is_dir($savePath.$path.$filename)){// 如果读取的某个对象是文件夹，则递归
                        self::addFileToZip($path.'/'.$filename,$zip);
                    }else{ //将文件加入zip对象
                        $zip->addFile($savePath.$path.'/'.$filename);
                    }
                }
            }
            @closedir($path);

            if($zip -> close())
            {
                /** 删除压缩文件 */
                $handler=opendir($savePath.$path); //打开当前文件夹由$path指定。
                while(($filename=readdir($handler))!==false)
                {
                    if($filename != "." && $filename != "..")
                    unlink($savePath.$path.'/'.$filename);

                }
                @closedir($savePath.$path);
                rmdir($savePath.$path);

                if ($needDownload)
                {
                    Tools::download($savePath.$saveName.'.zip',$saveName.'.zip');
                    unlink($savePath.$saveName.'.zip');
                }else{
                    echo "压缩成功";
                }

            }else{
                echo  '压缩失败';
            }

        }

    }
    /**
     * 下载文件接口
     * @param  [type] $filePath [目标文件路径]
     * @param  [type] $filename [目标文件的名称]
     * @return [type]           [description]
     */
    public static function download($filePath,$filename)
    {
        header("Content-type:text/html;charset=utf-8");

        $file_path=$filePath;
        //用以解决中文不能显示出来的问题
        $file_path=iconv("utf-8","gb2312",$file_path);

        if(!file_exists($file_path)){
            echo "没有该文件文件";
            return ;
        }
        $fp=fopen($file_path,"r");
        $file_size=filesize($file_path);
        //下载文件需要用到的头
        Header("Content-type: application/octet-stream");

        Header("Accept-Ranges: bytes");

        Header("Accept-Length:".$file_size);

        Header("Content-Disposition: attachment; filename=".$filename);

        $buffer=1024;

        $file_count=0;
        //向浏览器返回数据
        while(!feof($fp) && $file_count<$file_size)
        {
            $file_con=fread($fp,$buffer);

            $file_count+=$buffer;

            echo $file_con;

        }
        fclose($fp);
    }

}